<?php
namespace Org\Util;

/**
 * walletWeixinUtil
 * +----------------------------+
 * +         公用类方法         +
 * +----------------------------+
 * function getRealIp     得到 ip地址
 * function getNonceStr   得到 随机字符串
 * function curl_post_ssl 带curl 带证书请求
 * function _getSign      得到带签名的新的xml
 * @author sixian
 * @version v1.0
 * @copyright   
 */
class WalletWeixinUtil {
    public function __construct($options) {
        $this->options = $options;
    }
    
    /**
     * 获取用户 的ip
     * @return ip
     */
    public static function getRealIp() {
        $ip = "Unknown";

        if (isset($_SERVER["HTTP_X_REAL_IP"]) && !empty($_SERVER["HTTP_X_REAL_IP"])) {
            $ip = $_SERVER["HTTP_X_REAL_IP"];
        } elseif (isset($HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"]) && !empty($HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"])) {
            $ip = $HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"];
        } elseif (isset($HTTP_SERVER_VARS["HTTP_CLIENT_IP"]) && !empty($HTTP_SERVER_VARS["HTTP_CLIENT_IP"])) {
            $ip = $HTTP_SERVER_VARS["HTTP_CLIENT_IP"];
        } elseif (isset($HTTP_SERVER_VARS["REMOTE_ADDR"]) && !empty($HTTP_SERVER_VARS["REMOTE_ADDR"])) {
            $ip = $HTTP_SERVER_VARS["REMOTE_ADDR"];
        } elseif (getenv("HTTP_X_FORWARDED_FOR")) {
            $ip = getenv("HTTP_X_FORWARDED_FOR");
        } elseif (getenv("HTTP_CLIENT_IP")) {
            $ip = getenv("HTTP_CLIENT_IP");
        } elseif (getenv("REMOTE_ADDR")) {
            $ip = getenv("REMOTE_ADDR");
        }

        if ($ip == 'Unknown') {
            // 调试信息
            self:: debugErrorSendWx('获取不到ip地址', $_SERVER);
        }
        return $ip;
    }

    /**
     * 产生随机字符串，不长于32位
     * @param int $length
     * @return 产生的随机字符串
     */
    public static function getNonceStr($length = 32) {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str = "";
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    /**
     * 带证书请求xml 接口
     * @param   $url     请求的接口
     * @param   $vars    xml数据
     * @param   $second  最大超时时间 s
     * @param   $aHeader 请求头
     * @return 产生的随机字符串
     */
    public function curl_post_ssl($url, $vars, $second = 30, $aHeader = array()) {
        $ch = curl_init();
        //超时时间
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        //这里设置代理，如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '10.206.30.98');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

        //以下两种方式需选择一种
        //第一种方法，cert 与 key 分别属于两个.pem文件
        //默认格式为PEM，可以注释
        curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
        curl_setopt($ch, CURLOPT_SSLCERT, $this->options['sslcert_path']);
        //默认格式为PEM，可以注释
        curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
        curl_setopt($ch, CURLOPT_SSLKEY, $this->options['sslkey_path']);

        curl_setopt($ch, CURLOPT_CAINFO, $this->options['sslrootca_path']);
        //第二种方式，两个文件合成一个.pem文件
        //curl_setopt($ch,CURLOPT_SSLCERT,SITE_PATH.'/all.pem');

        if (count($aHeader) >= 1) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
        }

        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $vars);
        $data = curl_exec($ch);
        if ($data) {
            curl_close($ch);
            $debugArray = @simplexml_load_string($data, NULL, LIBXML_NOCDATA);
            $debugArrayNew['状态'] = $debugArray['return_code'];
            $debugArrayNew['返回信息'] = @$debugArray['return_msg'];

            // 调试信息
            //self:: debugErrorSendWx('发红包微信接口返回', $debugArrayNew );

            return $data;
        } else {
            $error = curl_errno($ch);
            //echo "call faild, errorCode:$error\n";
            // 调试信息
            self:: debugErrorSendWx('sendWallet_app => curl_post_ssl出错', array('error' => $error));
            curl_close($ch);
            return false;
        }
    }

    /**
     * +---------------------------+
     * +       生成支付签名        +
     * +---------------------------+
     * @param  $xmlData  xml数据
     * @return 带上签名的xmlData
     */
    public function _getSign($xmlData) {
        $res = @simplexml_load_string($xmlData, NULL, LIBXML_NOCDATA);
        $res = json_decode(json_encode($res), true);
        unset($res['sign']);
        ksort($res);
        $stringA = "";
        foreach ($res as $key => $value) {
            if (!empty($value)) {
                $stringA .= "{$key}=$value&";
            }
        }

        $stringSignTemp = "{$stringA}key=" . $this->options['key'];
        $sign = md5($stringSignTemp);

        $xmlData = str_replace("{sign}", $sign, $xmlData);
        return $xmlData;
    }

    //签名检查算法  signature、timestamp、nonce

    /**
     * +---------------------------+
     * +       生成验证签名        +
     * +---------------------------+
     * @param  $signature   生成的签名
     * @param  $timestamp   生成的签名
     * @param  $nonce       生成的签名
     * @param  $privateKey  生成的签名
     * @return bool  true or false
     */
    public static function checkSignature($signature, $timestamp, $nonce, $privateKey = '') {
        if (empty($signature)) {
            return false;
        }

        $time = time();
        if ($time - $timestamp > 10) {
            return false;
        }

        $token = empty($privateKey) ? $this->options['privateKey'] : $privateKey;
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode($tmpArr);
        $tmpStr = sha1($tmpStr);

        if ($tmpStr == $signature) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 调试微信接收信息公用方法
     * @param $title 标题
     * @param $array 要发送的数据
     * @return 微信官方返回的数据
     */
    public function debugErrorSendWx($title = "调试信息", $array = array()) {

        if (1) {
            $tipMsg = "红包接口【" . $title . "】\n";
            foreach ((array) $array as $ney => $na) {
                $tipMsg .= $ney . '：' . $na . ';\n';
            }
            $tipMsg .= "时间：" . date('Y-m-d H:i:s');

            @error_log("{$tipMsg}", 3, "/var/log/debug.log");
        } else {
            echo "not off debug!";
        }
    }

    /**
     * curl请求
     * @param $url        请求的api
     * @param $post       是否开户post
     * @param $postFields post的数据
     * @return 接口返回的数据
     */
    public static function curlGet($url, $post = false, $postFields = array(), $timeout = 2) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);

        if ($post && !empty($postFields)) {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
        }

        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }

}